/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ProjectSkyfire <http://www.projectskyfire.org/>
 *
 * Copyright (C) 2011 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef ARKCORECORE_GOSSIP_H
#define ARKCORECORE_GOSSIP_H

#include "Common.h"
#include "QuestDef.h"
#include "NPCHandler.h"

class WorldSession;

#define GOSSIP_MAX_MENU_ITEMS 64                            // client supported items unknown, but provided number must be enough
#define DEFAULT_GOSSIP_MESSAGE              0xffffff

enum Gossip_Option
{
    GOSSIP_OPTION_NONE = 0,          //UNIT_NPC_FLAG_NONE                (0)
    GOSSIP_OPTION_GOSSIP = 1,          //UNIT_NPC_FLAG_GOSSIP              (1)
    GOSSIP_OPTION_QUESTGIVER = 2,          //UNIT_NPC_FLAG_QUESTGIVER          (2)
    GOSSIP_OPTION_VENDOR = 3,          //UNIT_NPC_FLAG_VENDOR              (128)
    GOSSIP_OPTION_TAXIVENDOR = 4,          //UNIT_NPC_FLAG_TAXIVENDOR          (8192)
    GOSSIP_OPTION_TRAINER = 5,          //UNIT_NPC_FLAG_TRAINER             (16)
    GOSSIP_OPTION_SPIRITHEALER = 6,          //UNIT_NPC_FLAG_SPIRITHEALER        (16384)
    GOSSIP_OPTION_SPIRITGUIDE = 7,          //UNIT_NPC_FLAG_SPIRITGUIDE         (32768)
    GOSSIP_OPTION_INNKEEPER = 8,          //UNIT_NPC_FLAG_INNKEEPER           (65536)
    GOSSIP_OPTION_BANKER = 9,          //UNIT_NPC_FLAG_BANKER              (131072)
    GOSSIP_OPTION_PETITIONER = 10,          //UNIT_NPC_FLAG_PETITIONER          (262144)
    GOSSIP_OPTION_TABARDDESIGNER = 11,          //UNIT_NPC_FLAG_TABARDDESIGNER      (524288)
    GOSSIP_OPTION_BATTLEFIELD = 12,          //UNIT_NPC_FLAG_BATTLEFIELDPERSON   (1048576)
    GOSSIP_OPTION_AUCTIONEER = 13,          //UNIT_NPC_FLAG_AUCTIONEER          (2097152)
    GOSSIP_OPTION_STABLEPET = 14,          //UNIT_NPC_FLAG_STABLE              (4194304)
    GOSSIP_OPTION_ARMORER = 15,          //UNIT_NPC_FLAG_ARMORER             (4096)
    GOSSIP_OPTION_UNLEARNTALENTS = 16,          //UNIT_NPC_FLAG_TRAINER             (16) (bonus option for GOSSIP_OPTION_TRAINER)
    GOSSIP_OPTION_UNLEARNPETTALENTS = 17,          //UNIT_NPC_FLAG_TRAINER             (16) (bonus option for GOSSIP_OPTION_TRAINER)
    GOSSIP_OPTION_LEARNDUALSPEC = 18,          //UNIT_NPC_FLAG_TRAINER             (16) (bonus option for GOSSIP_OPTION_TRAINER)
    GOSSIP_OPTION_OUTDOORPVP = 19,          //added by code (option for outdoor pvp creatures)
    GOSSIP_OPTION_REFORGE = 20,          //UNIT_NPC_FLAG_REFORGE             (134217728)
    GOSSIP_OPTION_MAX
};

enum GossipOptionIcon
{
    GOSSIP_ICON_CHAT = 0,          // white chat bubble
    GOSSIP_ICON_VENDOR = 1,          // brown bag
    GOSSIP_ICON_TAXI = 2,          // flightmarker (paperplane)
    GOSSIP_ICON_TRAINER = 3,          // brown book (trainer)
    GOSSIP_ICON_INTERACT_1 = 4,          // golden interaction wheel
    GOSSIP_ICON_INTERACT_2 = 5,          // golden interaction wheel
    GOSSIP_ICON_MONEY_BAG = 6,          // brown bag (with gold coin in lower corner)
    GOSSIP_ICON_TALK = 7,          // white chat bubble (with "..." inside)
    GOSSIP_ICON_TABARD = 8,          // white tabard
    GOSSIP_ICON_BATTLE = 9,          // two crossed swords
    GOSSIP_ICON_DOT = 10,          // yellow dot/point
    GOSSIP_ICON_CHAT_11 = 11,          // white chat bubble
    GOSSIP_ICON_CHAT_12 = 12,          // white chat bubble
    GOSSIP_ICON_CHAT_13 = 13,          // white chat bubble
    GOSSIP_ICON_UNK_14 = 14,          // INVALID - DO NOT USE
    GOSSIP_ICON_UNK_15 = 15,          // INVALID - DO NOT USE
    GOSSIP_ICON_CHAT_16 = 16,          // white chat bubble
    GOSSIP_ICON_CHAT_17 = 17,          // white chat bubble
    GOSSIP_ICON_CHAT_18 = 18,          // white chat bubble
    GOSSIP_ICON_CHAT_19 = 19,          // white chat bubble
    GOSSIP_ICON_CHAT_20 = 20,          // white chat bubble
    GOSSIP_ICON_MAX
};

//POI icons. Many more exist, list not complete.
enum Poi_Icon
{
    ICON_POI_BLANK = 0,          // Blank (not visible)
    ICON_POI_GREY_AV_MINE = 1,          // Grey mine lorry
    ICON_POI_RED_AV_MINE = 2,          // Red mine lorry
    ICON_POI_BLUE_AV_MINE = 3,          // Blue mine lorry
    ICON_POI_BWTOMB = 4,          // Blue and White Tomb Stone
    ICON_POI_SMALL_HOUSE = 5,          // Small house
    ICON_POI_GREYTOWER = 6,          // Grey Tower
    ICON_POI_REDFLAG = 7,          // Red Flag w/Yellow !
    ICON_POI_TOMBSTONE = 8,          // Normal tomb stone (brown)
    ICON_POI_BWTOWER = 9,          // Blue and White Tower
    ICON_POI_REDTOWER = 10,          // Red Tower
    ICON_POI_BLUETOWER = 11,          // Blue Tower
    ICON_POI_RWTOWER = 12,          // Red and White Tower
    ICON_POI_REDTOMB = 13,          // Red Tomb Stone
    ICON_POI_RWTOMB = 14,          // Red and White Tomb Stone
    ICON_POI_BLUETOMB = 15,          // Blue Tomb Stone
    ICON_POI_16 = 16,          // Grey ?
    ICON_POI_17 = 17,          // Blue/White ?
    ICON_POI_18 = 18,          // Blue ?
    ICON_POI_19 = 19,          // Red and White ?
    ICON_POI_20 = 20,          // Red ?
    ICON_POI_GREYLOGS = 21,          // Grey Wood Logs
    ICON_POI_BWLOGS = 22,          // Blue and White Wood Logs
    ICON_POI_BLUELOGS = 23,          // Blue Wood Logs
    ICON_POI_RWLOGS = 24,          // Red and White Wood Logs
    ICON_POI_REDLOGS = 25,          // Red Wood Logs
    ICON_POI_26 = 26,          // Grey ?
    ICON_POI_27 = 27,          // Blue and White ?
    ICON_POI_28 = 28,          // Blue ?
    ICON_POI_29 = 29,          // Red and White ?
    ICON_POI_30 = 30,          // Red ?
    ICON_POI_GREYHOUSE = 31,          // Grey House
    ICON_POI_BWHOUSE = 32,          // Blue and White House
    ICON_POI_BLUEHOUSE = 33,          // Blue House
    ICON_POI_RWHOUSE = 34,          // Red and White House
    ICON_POI_REDHOUSE = 35,          // Red House
    ICON_POI_GREYHORSE = 36,          // Grey Horse
    ICON_POI_BWHORSE = 37,          // Blue and White Horse
    ICON_POI_BLUEHORSE = 38,          // Blue Horse
    ICON_POI_RWHORSE = 39,          // Red and White Horse
    ICON_POI_REDHORSE = 40
// Red Horse
};

struct GossipMenuItem
{
    uint8 m_gIcon;
    bool m_gCoded;
    std::string m_gMessage;
    uint32 m_gSender;
    uint32 m_gOptionId;
    std::string m_gBoxMessage;
    uint32 m_gBoxMoney;
};

typedef std::vector<GossipMenuItem> GossipMenuItemList;

struct GossipMenuItemData
{
    uint32 m_gAction_menu;
    uint32 m_gAction_poi;
    uint32 m_gAction_script;
};

typedef std::vector<GossipMenuItemData> GossipMenuItemDataList;

struct QuestMenuItem
{
    uint32 m_qId;
    uint8 m_qIcon;
};

typedef std::vector<QuestMenuItem> QuestMenuItemList;

class GossipMenu
{
public:
    GossipMenu ();
    ~GossipMenu ();

    void AddMenuItem (uint8 Icon, const std::string& Message, bool Coded = false);
    void AddMenuItem (uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded = false);

    // for using from scripts, don't must be inlined
    void AddMenuItem (uint8 Icon, char const* Message, bool Coded = false);
    void AddMenuItem (uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false);

    void SetMenuId (uint32 menu_id)
    {
        m_gMenuId = menu_id;
    }
    uint32 GetMenuId () const
    {
        return m_gMenuId;
    }

    void AddGossipMenuItemData (uint32 action_menu, uint32 action_poi, uint32 action_script);

    unsigned int MenuItemCount () const
    {
        return m_gItems.size();
    }

    bool Empty () const
    {
        return m_gItems.empty();
    }

    GossipMenuItem const& GetItem (unsigned int Id) const
    {
        return m_gItems[Id];
    }

    GossipMenuItemData const& GetItemData (unsigned int indexId) const
    {
        return m_gItemsData[indexId];
    }

    uint32 MenuItemSender (unsigned int ItemId);
    uint32 MenuItemAction (unsigned int ItemId);
    bool MenuItemCoded (unsigned int ItemId);

    void ClearMenu ();

protected:
    GossipMenuItemList m_gItems;
    GossipMenuItemDataList m_gItemsData;

    uint32 m_gMenuId;
};

class QuestMenu
{
public:
    QuestMenu ();
    ~QuestMenu ();

    void AddMenuItem (uint32 QuestId, uint8 Icon);
    void ClearMenu ();

    uint8 MenuItemCount () const
    {
        return m_qItems.size();
    }

    bool Empty () const
    {
        return m_qItems.empty();
    }

    bool HasItem (uint32 questid);

    QuestMenuItem const& GetItem (uint16 Id) const
    {
        return m_qItems[Id];
    }

protected:
    QuestMenuItemList m_qItems;
};

class PlayerMenu
{
private:
    GossipMenu mGossipMenu;
    QuestMenu mQuestMenu;
    WorldSession* pSession;

public:
    PlayerMenu (WorldSession *Session);
    ~PlayerMenu ();

    GossipMenu& GetGossipMenu ()
    {
        return mGossipMenu;
    }
    QuestMenu& GetQuestMenu ()
    {
        return mQuestMenu;
    }

    bool Empty () const
    {
        return mGossipMenu.Empty() && mQuestMenu.Empty();
    }

    void ClearMenus ();
    uint32 GossipOptionSender (unsigned int Selection);
    uint32 GossipOptionAction (unsigned int Selection);
    bool GossipOptionCoded (unsigned int Selection);

    void SendGossipMenu (uint32 TitleTextId, uint64 npcGUID);
    void CloseGossip ();
    void SendPointOfInterest (float X, float Y, uint32 Icon, uint32 Flags, uint32 Data, const char * locName);
    void SendPointOfInterest (uint32 poi_id);
    void SendTalking (uint32 textID);
    void SendTalking (char const * title, char const * text);

    /*********************************************************/
    /***                    QUEST SYSTEM                   ***/
    /*********************************************************/
    void SendQuestGiverStatus (uint32 questStatus, uint64 npcGUID);

    void SendQuestGiverQuestList (QEmote eEmote, const std::string& Title, uint64 npcGUID);

    void SendQuestQueryResponse (Quest const *pQuest);
    void SendQuestGiverQuestDetails (Quest const *pQuest, uint64 npcGUID, bool ActivateAccept);

    void SendQuestGiverOfferReward (Quest const* pQuest, uint64 npcGUID, bool EnableNext);
    void SendQuestGiverRequestItems (Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel);
};
#endif
